package fileServiceAndroid;

import gui.WindowsApplication;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;

import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;


import entities.CSFileWrapper;
import entities.Device;


public class FileServiceHost implements Runnable{
	private SSLServerSocket messageService;
	private WindowsApplication windowsApp;
	
	public FileServiceHost(WindowsApplication windowsApp){
		this.windowsApp = windowsApp;
	}
	
	public void run(){
		try {
			startService();

			while(true){
				handleRequest();
			}
		} catch (IOException e) {e.printStackTrace();
		}
	}

	public void handleRequest(){
		System.out.println("FileServiceHost: handleRequest()");
		try{
			SSLSocket client = (SSLSocket) messageService.accept();
			InputStreamReader isr = new InputStreamReader(client.getInputStream());
			BufferedReader in = new BufferedReader(isr);
			
			OutputStreamWriter osw = new OutputStreamWriter(client.getOutputStream());
			BufferedWriter out = new BufferedWriter(osw); 
			
			String methodName = "";
			if((methodName = in.readLine()) != null){
				if(methodName.equalsIgnoreCase("getfilenames")){
					out.write("arlistart");
					out.write("\n");
					out.flush();
					for(String s : getFileNames()){
						out.write(s);
						out.write("\n");
						out.flush();
					}
					out.write("arliend");
					out.write("\n");
					out.flush();

					String received = in.readLine();
					if(received.equalsIgnoreCase("received")){
						System.out.println("FSH: GetFileNames: Done");
					}else{
						System.out.println("FileServiceHost: Invalid Message: " + received);
					}
				}else if(methodName.equalsIgnoreCase("getdevice")){
					Device d = getDevice();
					
					out.write("devicestart");
					out.write("\n");
					out.flush();
					
					String device = "Name:"+d.getDeviceName()+
							";IP:"+d.getIpAddress()+
							";UUID:"+d.getUUID()+
							";Type:"+d.getDeviceType();
					
					out.write(device);
					out.write("\n");
					out.flush();
					
					if(d.getConnectedDevices().size() > 1){
						out.write("arlistart");
						out.write("\n");
						out.flush();
						for(String connection : d.getConnectedDevices()){
							out.write(connection);
							out.write("\n");
							out.flush();
						}
						out.write("arliend");
						out.write("\n");
						out.flush();
					}
					out.write("deviceend");
					out.write("\n");
					out.flush();
					
					String recieved = in.readLine();
				}else if(methodName.equalsIgnoreCase("sendfile")){//writes to disk
					out.write("sendfilename");
					out.write("\n");
					out.flush();
					String fileName = in.readLine();
					
					String startFileService = in.readLine();
					FileReceiverService fs = new FileReceiverService();
					if(startFileService.equalsIgnoreCase("startfileservice")){
						fs.startReceiveFileService();
					
						out.write("fileservicestarted");
						out.write("\n");
						out.flush();
						
						out.write("sendfilesize");
						out.write("\n");
						out.flush();
						
						String fileSizeString = in.readLine();
//						int fileSize = (int) in.readLine().charAt(0)
						int fileSize = Integer.parseInt(fileSizeString);
							SSLSocket clientFile = fs.receiveFileConnection(); 
							CSFileWrapper file = fs.receiveFile(clientFile, fileName, fileSize);
							fs.stopReceiveFileService();
							
						out.write("filereceived");
						out.write("\n");
						out.flush();
						
						sendFile(file);
					}
	
				}else if(methodName.equalsIgnoreCase("getfile")){//send file to client
					out.write("sendfilename");
					out.write("\n");
					out.flush();
					String fileName = in.readLine();
					CSFileWrapper file = getFile(fileName);
					
					out.write("startfileservice");
					out.write("\n");
					out.flush();
					String serviceStarted = in.readLine();
					if(serviceStarted.equalsIgnoreCase("fileservicestarted")){
						String fileSize = in.readLine();
						if(fileSize.equalsIgnoreCase("sendfilesize")){
							out.write(String.valueOf(file.getData().length));
							out.write("\n");
							out.flush();
							FileReceiverService fs = new FileReceiverService();
							try{
								fs.sendFile(file.getData(), client.getInetAddress());
							}catch(UnknownHostException e){e.printStackTrace();}
						}else{
							System.out.println("FileServiceHost Invalid Message: " + fileSize);
						}
					}else{
						System.out.println("FileServiceHost Invalid Message: " + serviceStarted);
					}
					
					String fileReceived = in.readLine();
					if(fileReceived.equalsIgnoreCase("received")){
						System.out.println("FileServiceHost Finished");
					}else{
						System.out.println("FileServiceHost Invalid Message: " + fileReceived);
					}
				}else{
					out.write("Invalid Request");
					out.write("\n");
					out.flush();
				}
				in.close();
				out.close();
				client.close();
			}else{
				System.out.println(methodName + " OUTTER ELSE");
			}
			System.out.println(methodName + "OUTSIDE");
		}catch(IOException e){e.printStackTrace();}
	}
	
	public ArrayList<String> getFileNames(){
		System.out.println("FileServiceHost: getFileNames()");
		return windowsApp.getFileIO().getFileNames();
	}
	public CSFileWrapper getFile(String fileName){
		System.out.println("FileServiceHost: getFile()");
		return windowsApp.getFileIO().getFile(fileName);
	}
	public void sendFile(CSFileWrapper file){
		System.out.println("FileServiceHost: sendFile()");
		windowsApp.getFileIO().writeFile(file);
	}
	public Device getDevice(){
		System.out.println("FileServiceHost: getDevice()");
		return windowsApp.getCSEP().getConnectionServiceImpPort().getDeviceByUUID(windowsApp.getDevice().getUUID());
	}
	
	//MessageService	
	public void startService() throws IOException{
		System.out.println("FileServiceHost: startService()");
		SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
		messageService = (SSLServerSocket)factory.createServerSocket(2081);
		messageService.setEnabledCipherSuites(messageService.getSupportedCipherSuites());
//			messageService = new ServerSocket(2081);
	}
	public void stopService() throws IOException{
		System.out.println("FileServiceHost: stopService()");
			messageService.close();
	}
	public SSLSocket receiveMessageConnection() throws IOException{
		System.out.println("FileServiceHost: receiveMessageConnection()");
			SSLSocket client = (SSLSocket) messageService.accept();
			return client;
	}
	
}
